package com.yfcloud.middleware.storage.tools;

import com.yfcloud.middleware.storage.config.ZooKeeperConfig;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class ZKClientUtil {

    private static CountDownLatch watch = new CountDownLatch(1);
    /**
     * 判断节点是否存在
     * */
    public static boolean isExistNode(String path) {
        CuratorFramework client = ZooKeeperConfig.getClient();
        client.sync() ;
        try {
            Stat stat = client.checkExists().forPath(path);
            return client.checkExists().forPath(path) != null;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 创建节点
     * */
    public static void createNode(CreateMode mode, String path) {
        CuratorFramework client = ZooKeeperConfig.getClient() ;
        try {
            // 递归创建所需父节点
            client.create().creatingParentsIfNeeded().withMode(mode).forPath(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置节点数据
     * */
    public static void setNodeData(String path, String nodeData) {
        CuratorFramework client = ZooKeeperConfig.getClient() ;
        try {
            // 设置节点数据
            client.setData().forPath(path, nodeData.getBytes("UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建节点并关联数据
     * */
    public static void createNodeAndData(CreateMode mode, String path, String nodeData) {
        CuratorFramework client = ZooKeeperConfig.getClient() ;
        try {
            // 创建节点，关联数据
            client.create().creatingParentsIfNeeded().withMode(mode)
                    .forPath(path,nodeData.getBytes("UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     *  数据读取和转换
     * **/
    public static  String getNodeData(String path) {
        CuratorFramework client = ZooKeeperConfig.getClient() ;
        try {
            // 数据读取和转换
            byte[] dataByte = client.getData().forPath(path) ;
            String data = new String(dataByte,"UTF-8") ;
            if (StringUtils.isNotEmpty(data)){
                return data ;
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取子节点
     * */
    public static List<String> getNodeChild(String path) {
        CuratorFramework client = ZooKeeperConfig.getClient() ;
        List<String> nodeChildDataList = new ArrayList<>();
        try {
            // 节点下数据集
            nodeChildDataList = client.getChildren().forPath(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return nodeChildDataList;
    }

    /**
     * 删除节点
     * */
    public static void deleteNode(String path, Boolean recursive) {
        CuratorFramework client = ZooKeeperConfig.getClient() ;
        try {
            if(recursive) {
                // 递归删除节点
                client.delete().guaranteed().deletingChildrenIfNeeded().forPath(path);
            } else {
                // 删除单个节点
                client.delete().guaranteed().forPath(path);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取读写锁
     * */
    public static InterProcessReadWriteLock getReadWriteLock(String path) {
        CuratorFramework client = ZooKeeperConfig.getClient() ;
        // 写锁互斥、读写互斥
        InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(client, path);
        return readWriteLock ;
    }

    /**
    * 监听数据变化
    * */
    public static void RegistryListen(String path, TreeCacheListener treeCacheListener){
        try {
            TreeCache treeCache = new TreeCache(ZooKeeperConfig.getClient(), path);
            treeCache.getListenable().addListener(treeCacheListener);
            treeCache.start();
            watch.await();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
